package com.yj.auto.core.jfinal.context;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.jfinal.config.Routes;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.yj.auto.core.base.annotation.Controller;
import com.yj.auto.core.jfinal.base.BaseController;
import com.yj.auto.utils.ClassUtil;

/**
 * 自动绑定（来自jfinal ext) 1.如果没用加入注解，必须以Controller结尾,自动截取前半部分为key
 * 2.加入ControllerBind的 获取 key
 */
public class AutoRoutesConfig extends Routes {

	protected final Log logger = Log.getLog(getClass());

	private List<Class<? extends BaseController>> excludeClasses = new ArrayList<Class<? extends BaseController>>();

	private List<String> includeJars = new ArrayList<String>();

	private boolean autoScan = true;

	private String suffix = "Controller";

	public AutoRoutesConfig() {
	}

	public AutoRoutesConfig(boolean autoScan) {
		this.autoScan = autoScan;
	}

	public AutoRoutesConfig addJar(String jarName) {
		if (StrKit.notBlank(jarName)) {
			includeJars.add(jarName);
		}
		return this;
	}

	public AutoRoutesConfig addJars(String jarNames) {
		if (StrKit.notBlank(jarNames)) {
			addJars(jarNames.split(","));
		}
		return this;
	}

	public AutoRoutesConfig addJars(String[] jarsName) {
		includeJars.addAll(Arrays.asList(jarsName));
		return this;
	}

	public AutoRoutesConfig addJars(List<String> jarsName) {
		includeJars.addAll(jarsName);
		return this;
	}

	public AutoRoutesConfig addExcludeClass(Class<? extends BaseController> clazz) {
		if (clazz != null) {
			excludeClasses.add(clazz);
		}
		return this;
	}

	public AutoRoutesConfig addExcludeClasses(Class<? extends BaseController>[] clazzes) {
		excludeClasses.addAll(Arrays.asList(clazzes));
		return this;
	}

	public AutoRoutesConfig addExcludeClasses(List<Class<? extends BaseController>> clazzes) {
		excludeClasses.addAll(clazzes);
		return this;
	}

	@Override
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void config() {
		setBaseViewPath(com.yj.auto.Constants.SYS_VIEW_ROOT);
		if (!autoScan) {
			return;
		}
		List<Class<? extends BaseController>> controllerClasses = ClassUtil.findInClasspathAndJars(BaseController.class, includeJars);
		Controller controllerBind = null;
		for (Class controllerCls : controllerClasses) {
			if (ClassUtil.isAbstract(controllerCls))
				continue;
			if (excludeClasses.contains(controllerCls)) {
				continue;
			}
			if (!controllerCls.getSimpleName().endsWith(suffix)) {
				logger.debug("fail routes.add " + controllerCls.getName() + " is suffix not " + suffix);
				continue;
			}

			String controllerKey = null;
			String viewPath = null;
			controllerBind = (Controller) controllerCls.getAnnotation(Controller.class);
			if (controllerBind != null) {
				controllerKey = controllerBind.key();
				viewPath = controllerBind.viewPath();
			}
			if (StrKit.isBlank(controllerKey)) {// 默认cotroller key
				controllerKey = getControllerKey(controllerCls);
			}
			if (StrKit.isBlank(viewPath)) {
				this.add(controllerKey, controllerCls);
			} else {
				this.add(controllerKey, controllerCls, viewPath);
			}
			logger.debug("routes.add: key= " + controllerKey + " ,viewPath= " + viewPath + " ,class= " + controllerCls);
		}
	}

	private String getControllerKey(Class<BaseController> clazz) {
		String controllerKey = "/" + StrKit.firstCharToLowerCase(clazz.getSimpleName());
		controllerKey = controllerKey.substring(0, controllerKey.indexOf(suffix));
		return controllerKey;
	}

	public List<Class<? extends BaseController>> getExcludeClasses() {
		return excludeClasses;
	}

	public void setExcludeClasses(List<Class<? extends BaseController>> excludeClasses) {
		this.excludeClasses = excludeClasses;
	}

	public List<String> getIncludeJars() {
		return includeJars;
	}

	public void setIncludeJars(List<String> includeJars) {
		this.includeJars = includeJars;
	}

	public void setAutoScan(boolean autoScan) {
		this.autoScan = autoScan;
	}

	public String getSuffix() {
		return suffix;
	}

	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}

}
